//
// Created by ta&to on 2022/9/28.
//

#include "http_connect.h"
#if defined(SOCKET_SERVER_POLL) && !defined(PLATFORM_WINDOWS)
#include <poll.h>

#define POLLRDNEW	0x2000

static void _init_poll(log_t *logt, struct http_socket_event_loop_s *hset) {
    hset->current_link = 0;
    hset->poll_ev_fds = (struct pollfd*)http_calloc(hset->max_link * sizeof(struct pollfd));
}
// 初始化fds结构体数组
static void _create_poll(log_t *logt, struct http_socket_event_loop_s *hset)
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        hset->poll_ev_fds[i].fd = -1;
        hset->poll_ev_fds[i].events = 0;
        hset->poll_ev_fds[i].revents = 0;
    }
}

// 向fds结构体数组中插入一个文件描述符
void _add_event(log_t *logt, struct http_socket_event_loop_s *hset, int fd, uint32_t event)//此处flag是为了判断是文件描述符c，还是listenfd，来设置events
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        if(hset->poll_ev_fds[i].fd == -1)
        {
            hset->poll_ev_fds[i].fd = fd;
            hset->poll_ev_fds[i].events = event;
            hset->poll_ev_fds[i].revents = POLLRDNEW;
            break;
        }
    }
    atomicIncr(hset->current_link, 1);
}

// 从fds结构体数组中删除一个文件描述符
int _del_event(log_t *logt, struct http_socket_event_loop_s *hset, int fd)
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        if(hset->poll_ev_fds[i].fd == fd)
        {
            hset->poll_ev_fds[i].fd = -1;
            hset->poll_ev_fds[i].events = 0;
            break;
        }
    }
    atomicDecr(hset->current_link, 1);
    return fd;
}

void init_poll(log_t *logt, struct http_socket_event_loop_s *hset) {
    _init_poll(logt, hset);
}

void create_poll(log_t *logt, struct http_socket_event_loop_s *hset) {
    _create_poll(logt, hset);
}

void add_event(log_t *logt, struct http_socket_event_loop_s *hset, int fd, uint32_t event) {
    _add_event(logt, hset, fd, event);
}

int del_event(log_t *logt, struct http_socket_event_loop_s *hset, int fd) {
    _del_event(logt, hset, fd);
}

// poll返回后，处理就绪的文件描述符
void _fd_handler(log_t *logt, struct http_socket_event_loop_s *hset, int listenfd)
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        if(hset->poll_ev_fds[i].fd == -1)
            continue;
        int fd = hset->poll_ev_fds[i].fd;
        if(fd == listenfd && hset->poll_ev_fds[i].revents & POLLIN) {           // 特殊处理 来的是链接请求
            http_socket_event_handle_t * handler = copy_func_handler(hset);
            int client_fd = conn_handler(logt, hset, handler);

            mutex_lock(&hset->hgdefc->event_fun_lock);
            char *fdc = (char *) http_calloc(sizeof(char) * http_numlen(client_fd) + 1);
            memset(fdc, 0, sizeof(fdc));
            http_sprintf(fdc, "%d", client_fd);
            do{             // 只要有修改的可能就要删除再添加，防止野指针问题
                RBtreenodedel(&hset->hgdefc->func_handler, fdc);
            } while (!RBtreenodeadd(&hset->hgdefc->func_handler, fdc, handler));
            http_free(fdc);
            mutex_unlock(&hset->hgdefc->event_fun_lock);

            // socketNonBlock(logt, client_fd);
            add_event(logt, hset, client_fd, POLLIN|POLLHUP);
        }
        else if(hset->poll_ev_fds[i].revents & POLLRDNEW || (hset->poll_ev_fds[i].revents == 0)) {        // 由于使用同一个描述符容器 新增加的描述符 或者本身没有事件到达 不处理
            continue;
        }
        else if(hset->poll_ev_fds[i].revents & POLLIN){        // 处理客户端发送来的数据
            debug(logt, "检查到[%d]有数据到达", fd);
            hset->current_fd = fd;

            mutex_lock(&hset->hgdefc->event_fun_lock);
            char *fdc = (char *) http_calloc(sizeof(char) * http_numlen(fd) + 1);
            memset(fdc, 0, sizeof(fdc));
            http_sprintf(fdc, "%d", fd);
            noder node = RBtreenodesel(&hset->hgdefc->func_handler, fdc);
            if(ISNULL(node)){
                mutex_unlock(&hset->hgdefc->event_fun_lock);
                continue;
            }
            http_socket_event_handle_t * handler = (http_socket_event_handle_t *)node->spot->value;
            http_free(fdc);
            mutex_unlock(&hset->hgdefc->event_fun_lock);

            if(ISNOTNULL(handler->func_read))
                handler->func_read(hset,  del_event(logt, hset, fd));
        }else{
            error(logt, "ev.events status[0x%02XD] %s", hset->poll_ev_fds[i].revents, strerror(errno));
            close(fd);
            del_event(logt, hset, fd);
        }
    }
}

void _poll_loop(log_t *logt, struct http_socket_event_loop_s *hset) {
    while(1)
    {
        if(poll(hset->poll_ev_fds, hset->maxfd, -1) <= 0)  // 设置poll
        {
            error(logt, "poll error\n");
            continue;
        }
        _fd_handler(logt, hset, hset->socket_fd);           // 检查是否有数据到达
    }
}

void Poll_do(log_t *logt, struct http_socket_event_loop_s *hset) {
    init_poll(logt, hset);
    create_poll(logt, hset);
    add_event(logt, hset, hset->socket_fd, POLLIN|POLLHUP);
    _poll_loop(logt, hset);
}
#endif
#if defined(SOCKET_SERVER_POLL)
int Poll_IO(log_t *logt, struct http_socket_event_loop_s *hset) {
#ifdef PLATFORM_WINDOWS
    error(logt, "Windows Platform no Support Poll");
#else
    Poll_do(logt, hset);
#endif
}
#endif
